class CubeService {

	int distance(cube1, cube2) {
		return Math.abs(cube1.x - cube2.x) + Math.abs(cube1.y - cube2.y) + Math.abs(cube1.z - cube2.z)
	}

	boolean areAdjacent(cube1, cube2) {
		return distance(cube1, cube2) == 1
	}
	
	boolean isMoveOk(cube1, cube2) {
		def dir = direction(cube1, cube2)
		return areAdjacent(cube1, cube2) && cube1.type.directionFree(dir) && cube2.type.directionFree(dir.opposite()) && cube2.type.free() && !cube2.unit
	}
	
	List getAdjacentCubes(cube) {
		return Direction.values().collect{ getAdjacentCube(cube, it) }
	}
	
	Map getDirectionsByCubes(cube) {
		def map = [:]
		Direction.values().each{
			def adjCube = getAdjacentCube(cube, it)
			if (adjCube && isMoveOk(cube, adjCube)) map[(adjCube.id)] = it 
		}
		return map
	}
	
	Cube getAdjacentCube(cube, direction) {
		return Cube.findWhere(place:cube.place, x:cube.x+direction.x, y:cube.y+direction.y, z:cube.z+direction.z)
	}
	
	Direction direction(cube1, cube2) {
		int x = cube2.x - cube1.x
		int y = cube2.y - cube1.y
		int z = cube2.z - cube1.z
		if (x > 0) return Direction.EAST
		if (x < 0) return Direction.WEST
		if (y > 0) return Direction.SOUTH
		if (y < 0) return Direction.NORTH
		if (z > 0) return Direction.CEILING
		if (z < 0) return Direction.FLOOR
	}
	
}